/**
 * @author xiao zhou
 * @lastEditTime 2021-06-10 15:21:29
 * @description
 */

const fse = require('fs-extra')
const { NodeSSH } = require('node-ssh')
const inquirer = require('inquirer')
const { deployConfigPath } = require('../config')
const { log, succeed, error, underline } = require('../utils')

// 是否确认
const isConfirm = message => inquirer.prompt([
  {
    'type': 'confirm',
    'name': 'confirm',
    message
  }
])

// 检查环境是否正确
const checkEnvConfig = (config, env) => {
  const keys = ['name', 'host', 'port', 'username', 'distPath', 'webDir']

  if (config) {
    keys.forEach(key => {
      if (!config?.['server']?.[env]?.[key] || config?.['server']?.[env]?.[key] === '/') {
        error(`配置错误: ${underline(`${env}环境`)} ${underline(`${key}属性`)} 未配置或格式不正确`)
        // eslint-disable-next-line no-undef
        process.exit(1)
      }
    })
  } else {
    error(`配置错误: （${underline(env)}） 未指定部署环境或指定部署环境配置不存在`)
    // eslint-disable-next-line no-undef
    process.exit(1)
  }
}

// 创建任务列表
const createTaskList = async (config, options) => {
  try {
    const { build } = options
    const ssh = new NodeSSH()
    let i = 0
    const { script, bakDir, isRemoveRemoteFile = true, isRemoveLocalFile = true } = config

    // 执行打包脚本
    script && build && await require('../tasks/executeBuild')(config, ++i)

    // 打包Zip
    await require('../tasks/buildZip')(config, ++i)

    // 连接ssh
    await require('../tasks/connectSSH')(ssh, config, ++i)

    // 上传本地文件
    await require('../tasks/uploadFile')(ssh, config, ++i)

    // 备份远程旧文件
    bakDir && await require('../tasks/backupRemoteFile')(ssh, config, ++i)

    // 删除远程旧文件
    isRemoveRemoteFile && await require('../tasks/removeRemoteFile')(ssh, config, ++i)

    // 解压远程文件
    await require('../tasks/unzipRemoteFile')(ssh, config, ++i)

    // 删除本地打包文件
    isRemoveLocalFile && await require('../tasks/removeLocalFile')(config, ++i)

    // 断开ssh
    await require('../tasks/disconnectSSH')(ssh)
  } catch (err) {
    error(err)
    // eslint-disable-next-line no-undef
    process.exit(1)
  }
}

module.exports = async options => {
  const { 'mode': env } = options
  if (fse.pathExistsSync(deployConfigPath)) {
    const config = require(deployConfigPath)
    const server = config['server']
    const projectName = config.projectName
    const currentTime = new Date().getTime()

    const createdEnvConfig = env => {
      checkEnvConfig(config, env)
      return { ...server[env], ...{
        'privateKey': config.privateKey,
        'passphrase': config.passphrase
      } }
    }

    if (server) {
      if (env) {
        const envConfig = createdEnvConfig(env)
        const answers = await isConfirm(`${underline(projectName)} 项目是否部署到 ${underline(envConfig.name)}?`)
        if (answers.confirm) {
          await createTaskList(envConfig, options)
          succeed(`恭喜您，${underline(projectName)} 项目已在${underline(envConfig.name)} 部署成功 耗时${(new Date().getTime() - currentTime) / 1000}s\n`)
          // eslint-disable-next-line no-undef
          process.exit(0)
        } else {
          log(`${underline(projectName)} 项目已取消部署！`)
          // eslint-disable-next-line no-undef
          process.exit(1)
        }
      } else {
        const envs = Object.keys(server)
        const answers = await isConfirm(`${underline(projectName)} 项目是否部署到 ${underline(`【 ${envs.join(',')} 】`)}v集群环境?`)
        if (answers.confirm) {
          for await (const env of envs) {
            const envConfig = createdEnvConfig(env)
            await createTaskList(envConfig, options)
            succeed(`${underline(envConfig.name)} 部署已完成`)
          }
          succeed(`恭喜您，${underline(projectName)} 项目已在${underline(`【 ${envs.join('&')}) 】`)}集群环境部署成功 耗时${(new Date().getTime() - currentTime) / 1000}s\n`)
        } else {
          log(`${underline(projectName)} 项目已取消部署！`)
          // eslint-disable-next-line no-undef
          process.exit(1)
        }
      }
    } else {
      error('请在配置文件中配置部署环境')
      // eslint-disable-next-line no-undef
      process.exit(1)
    }
  } else {
    error('deploy.config.js 文件不存在，请使用 @xz2xl/auto-deploy init 命令创建')
    // eslint-disable-next-line no-undef
    process.exit(1)
  }
}
